import OSS from 'ali-oss'
import { post } from './request'
import { getKnowledgeSts } from '@/api/knowledge'

interface StsResponse {
  accessKeyId: string
  accessKeySecret: string
  securityToken: string
  bucketName: string
  region: string
  filePath: string
}

interface UploadResult {
  url: string
  name: string
}

/**
 * 获取 OSS 上传凭证
 */
export const getOssSts = async (): Promise<StsResponse> => {
  return await post<StsResponse>('/ai-api/ai/user/sts')
}

/**
 * 上传文件到 OSS
 * @param file 要上传的文件
 * @param onProgress 上传进度回调
 * @returns 上传结果，包含文件URL和文件名
 */
export const uploadToOss = async (file: File, onProgress?: (percent: number) => void): Promise<UploadResult> => {
  try {
    // 获取 STS 凭证
    const sts = await getOssSts()

    // 创建 OSS 客户端
    const client = new OSS({
      accessKeyId: sts.accessKeyId,
      accessKeySecret: sts.accessKeySecret,
      stsToken: sts.securityToken,
      bucket: sts.bucketName,
      region: sts.region,
      refreshSTSToken: async () => {
        const newSts = await getOssSts()
        return {
          accessKeyId: newSts.accessKeyId,
          accessKeySecret: newSts.accessKeySecret,
          stsToken: newSts.securityToken
        }
      },
      refreshSTSTokenInterval: 300000, // 5分钟刷新一次
    })

    // 生成文件名
    const fileName = `${sts.filePath}${Date.now()}_${Math.random().toString(36).substring(2, 15)}.${file.name.split('.').pop()}`

    // 创建自定义请求选项，解决 ETag CORS 问题
    const customHeaders = {
      'x-oss-forbid-overwrite': 'true' // 防止覆盖同名文件
    };

    // 上传文件
    const result = await client.put(fileName, file)

    // 返回文件URL和文件名
    return {
      url: result.url,
      name: file.name
    }
  } catch (error) {
    console.error('文件上传失败:', error)
    throw new Error('文件上传失败')
  }
}

/**
 * 批量上传文件到 OSS
 * @param files 要上传的文件数组
 * @param onProgress 上传进度回调
 * @returns 上传结果数组
 */
export const uploadMultipleToOss = async (
  files: File[],
  onProgress?: (percent: number) => void
): Promise<UploadResult[]> => {
  const uploadPromises = files.map(file => uploadToOss(file, onProgress))
  return await Promise.all(uploadPromises)
}

/**
 * 上传文件到知识库 OSS
 * @param file 要上传的文件
 * @param onProgress 上传进度回调
 * @returns 上传结果，包含文件URL和文件名
 */
export const uploadToKnowledgeOss = async (file: File, onProgress?: (percent: number) => void): Promise<UploadResult> => {
  try {
    // 获取知识库 STS 凭证
    const sts = await getKnowledgeSts()

    // 创建 OSS 客户端
    const client = new OSS({
      accessKeyId: sts.accessKeyId,
      accessKeySecret: sts.accessKeySecret,
      stsToken: sts.securityToken,
      bucket: sts.bucketName,
      region: sts.region,
      refreshSTSToken: async () => {
        const newSts = await getKnowledgeSts()
        return {
          accessKeyId: newSts.accessKeyId,
          accessKeySecret: newSts.accessKeySecret,
          stsToken: newSts.securityToken
        }
      },
      refreshSTSTokenInterval: 300000, // 5分钟刷新一次
    })

    // 生成文件名
    const fileName = `${sts.filePath}${Date.now()}_${Math.random().toString(36).substring(2, 15)}.${file.name.split('.').pop()}`

    // 创建自定义请求选项，解决 ETag CORS 问题
    const customHeaders = {
      'x-oss-forbid-overwrite': 'true' // 防止覆盖同名文件
    };

    // 配置分片上传选项
    const options = {
      progress: (p: number) => {
        onProgress?.(p)
      },
      headers: customHeaders,
      parallel: 2, // 限制并发请求数
      partSize: 1024 * 1024, // 1MB 分片大小
      timeout: 120000 // 2分钟超时
    };

    // 使用分片上传
    let uploadResult;
    try {
      uploadResult = await client.multipartUpload(fileName, file, options);
    } catch (error) {
      console.error('OSS分片上传失败，尝试使用普通上传:', error);
      // 如果分片上传失败，尝试普通上传作为备选
      uploadResult = await client.put(fileName, file, { headers: customHeaders });
      // 上传完成后设置进度为100%
      onProgress?.(1);
    }

    // 构建OSS URL
    const url = client.signatureUrl(fileName)

    // 返回文件URL和文件名
    return {
      url,
      name: fileName
    }
  } catch (error) {
    console.error('知识库文件上传失败:', error)
    throw new Error('知识库文件上传失败')
  }
} 